﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PSDClientListener
{
    public class CycleRestartPSDClientManager
    {
        private System.Threading.Thread restartThread = null;
        private bool running = false;
        System.ServiceProcess.ServiceController serviceController = null;
        DateTime lastCheckpoint;
        int RestartInterval = 120;
        int RestartTimePoint = 45;
        int RestartWaiting = 5;

        private static object lock_restart = new object();
        private bool restarting = false;

        public void Init()
        {
            lastCheckpoint = DateTime.Parse("1900-1-1 00:00:00");
            RestartInterval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["RestartInterval"]);
            RestartTimePoint = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["RestartTimePoint"]);
            RestartWaiting = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["RestartWaiting"]);
        }

        public void Start()
        {
            serviceController = new System.ServiceProcess.ServiceController("PSDClientService");
            running = true;
            restartThread = new System.Threading.Thread(new System.Threading.ThreadStart(DoWork));
            restartThread.Start();
        }

        public void Stop()
        {
            running = false;

            try
            {
                restartThread.Abort();
            }
            catch { }
            finally
            {
                serviceController.Close();
            }
        }

        private void DoWork()
        {
            while (running)
            {
                if (CheckTime())
                {
                    RestartPSDClientService(RestartType.Normal);
                }

                System.Threading.Thread.Sleep(1000 * 60);
            }
        }

        private bool CheckTime()
        {
            bool ret = false;
            var now = DateTime.Now;

            var diff = now - lastCheckpoint;
            int rem = 0;
            Math.DivRem(now.Minute, RestartTimePoint, out rem);
            if (diff.TotalMinutes >= RestartInterval && rem == 0)
            {
                lastCheckpoint = now;
                ret = true;
            }
            else
            {
                ret = false;
            }
            return ret;
        }

        public void RestartPSDClientService(RestartType type)
        {
            lock (lock_restart)
            {
                if (restarting)
                {
                    return;
                }
                else
                {
                    restarting = true;
                }
            }

            string path = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "PSD", "Log", "listener.log");
            var sw = System.IO.File.AppendText(path);
            string log = "";
            try
            {
                //if (serviceController.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                //{
                //    serviceController.Stop();
                //    serviceController.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
                //    log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Routine Operation : PSDClientService Stopped";
                //    Console.WriteLine(log);
                //    sw.WriteLine(log);
                //    sw.Flush();
                //    log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Routine Operation : Waiting for " + RestartWaiting.ToString() + " mins to restart";
                //    Console.WriteLine(log);
                //    sw.WriteLine(log);
                //    sw.Flush();
                //    System.Threading.Thread.Sleep(1000 * 60 * RestartWaiting);
                //}

                log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Restart Type: " + type.ToString();
                Console.WriteLine(log);
                sw.WriteLine(log);
                sw.Flush();

                var p = System.Diagnostics.Process.GetProcessesByName("PSDClientService");
                if (p.Length > 0)
                {
                    p[0].Kill();

                    log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Process PSDClientService has been killed";
                    Console.WriteLine(log);
                    sw.WriteLine(log);
                    sw.Flush();
                    if (type == RestartType.Normal)
                    {
                        log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Waiting for " + RestartWaiting.ToString() + " mins to restart";
                        Console.WriteLine(log);
                        sw.WriteLine(log);
                        sw.Flush();
                        System.Threading.Thread.Sleep(1000 * 60 * RestartWaiting);
                    }
                }
                else
                {
                    log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " PSDClientService Not Running";
                    Console.WriteLine(log);
                    sw.WriteLine(log);
                    sw.Flush();
                }

                serviceController.Refresh();

                if (serviceController.Status == System.ServiceProcess.ServiceControllerStatus.Stopped)
                {
                    serviceController.Start();
                    serviceController.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
                    log = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " PSDClientService is Running";
                    Console.WriteLine(log);
                    sw.WriteLine(log);
                    Console.WriteLine("");
                    sw.WriteLine("");
                    sw.Flush();
                }
            }
            catch (Exception ex)
            {
                sw.WriteLine(System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + ex.Message + (ex.InnerException == null ? "" : ex.InnerException.Message));
                sw.Flush();
            }
            finally
            {
                sw.Close();
            }

            lock (lock_restart)
            {
                restarting = false;
            }
        }
    }

    public enum RestartType
    {
        Normal = 0,
        Timeout = 1,
    }
}
